package com.ncmmall.mall.controller.business.order;

import com.ncmmall.application.business.order.OrderApplication;
import com.ncmmall.application.securitys.logs.OperationLogApplication;
import com.ncmmall.application.util.WechatMessageUtils;
import com.feijin.commons.excel.ExcelExports;
import com.feijin.commons.exceptions.IllegalRequestException;
import com.feijin.commons.lang.Dates;
import com.feijin.commons.webs.Webs;
import com.ncmmall.domain.business.express.Express;
import com.ncmmall.domain.business.express.QExpress;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.order.Order;
import com.ncmmall.domain.business.order.OrderDetail;
import com.ncmmall.domain.business.order.QOrder;
import com.ncmmall.domain.business.order.delivery.QSupplierOrderDelivery;
import com.ncmmall.domain.business.order.delivery.SupplierOrderDelivery;
import com.ncmmall.mall.controller.securitys.shiro.Securitys;
import com.ncmmall.mall.params.PageParams;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 订单管理
 *
 * @author linxs
 * @date 2019-07-10 17:44
 */
@Controller
@RequestMapping(value = "/supplier/order")
@Slf4j
@RequiredArgsConstructor
public class SupplierOrderController {

    private final QueryChannelService queryChannelService;
    private final OrderApplication orderApplication;
    private final OperationLogApplication logApplication;

    /**
     * 订单列表
     */
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    public String list(Model model, PageParams pageParams, Order order) throws ParseException {
        QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageParams.getPageNo());
        Map<String, Object> params = Maps.newHashMap();
        params.put("id", Securitys.currentUser().getId());
        String hql = builderSQL("select u from Order u where u.merchant.id = :id and u.isSupplier = 1 ", params, order);
        QueryPage<Order> page = queryChannelService.findPage(hql, pageRequest.setParams(params), Order.class);
        model.addAttribute("page", page).addAttribute("params", order);

        return "supplier/order/list";
    }


    /**
     * 导出Excel
     */
    @RequestMapping(value = "/exports", method = RequestMethod.GET)
    private void exports(HttpServletRequest request, HttpServletResponse response, Order order) throws ParseException {
        Map<String, Object> params = Maps.newHashMap();
        params.put("id", Securitys.currentUser().getId());

        String sql = "select u from Order u where u.merchant.id = :id and u.isSupplier = 1 ";
        String hql = builderSQL(sql, params, order);

        List<Order> result = queryChannelService.findAll(hql, params, Order.class);
        for (Order item : result) {

            List<String> names = Lists.newArrayList();
            for (OrderDetail detail : item.getDetails()) {
                names.add(detail.getGoodsName());
            }

            item.setExpressCompany(Joiner.on("、").join(names));

        }

        Map<String, Object> data = ImmutableMap.of("result", result);
        ExcelExports document = new ExcelExports.Templates().formTemplate("merchantOrders.ftl").bind(data).store("merchantOrders.xls").build();

        try {
            document.generate();
            Webs.download(request, response, document.getFile(), "订单" + Dates.transDateToStr(new Date()) + ".xls");

        } catch (Exception e) {
            log.error("[导出异常]", e);
        }
    }

    /**
     * 去发货
     */
    @RequestMapping(value = "/{id}/delivery", method = RequestMethod.GET)
    private String delivery(Model model, @PathVariable("id") long id) {

        Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);
        List<Express> expresses = queryChannelService.findAll(QExpress.express.status.eq(2), Express.class);

        model.addAttribute("order", order).addAttribute("expresses", expresses).addAttribute("_method", "PUT");

        return "supplier/order/delivery";
    }

    /**
     * 审核线下转账
     */
    @RequestMapping(value = "/{id}/process", method = RequestMethod.GET)
    private String process(Model model, @PathVariable("id") long id) {

        Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

        model.addAttribute("order", order).addAttribute("_method", "PUT");

        return "supplier/order/process";
    }

    /**
     * 审核线下转账
     */
    @RequestMapping(value = "/{id}/process", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> process(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, Order params) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }

            orderApplication.processBankCardPay(params);
            logApplication.eventOfMerchant(Securitys.currentUser(), "线下转账审核", Securitys.getIp(request));

            return ImmutableMap.of("status", true);

        } catch (Exception e) {
            log.error("[线下转账审核异常]", e);
            return ImmutableMap.of("status", false, "message", "线下转账审核异常");
        }
    }


    /**
     * 发货
     */
    @RequestMapping(value = "/{id}/delivery", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> delivery(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, Order params) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }

            orderApplication.purchaseOrderDelivery(params);
            logApplication.eventOfMerchant(Securitys.currentUser(), "订单发货", Securitys.getIp(request));

            Order order = queryChannelService.findOne(QOrder.order.id.eq(params.getId()), Order.class);
            Express express = queryChannelService.findOne(QExpress.express.expressCompanyCode.eq(params.getExpressCode()), Express.class);

            JSONObject item = new JSONObject();
            item.put("number2", JSONObject.fromObject(ImmutableMap.of("value", order.getOrderNo())));
            item.put("date5", JSONObject.fromObject(ImmutableMap.of("value", new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(order.getDeliveryTime()))));
            item.put("thing1", JSONObject.fromObject(ImmutableMap.of("value", order.getDetails().get(0).getSku().getGoods().getName())));
            item.put("phrase3", JSONObject.fromObject(ImmutableMap.of("value", express.getName())));
            item.put("character_string4", JSONObject.fromObject(ImmutableMap.of("value", params.getExpressesNo())));

            WechatMessageUtils.send(order.getMember().getOpenId(), "0CIwJhN8oBSl-zGgT7IRL-k0HfkWt-0duPrGcFayfBo", item.toString());

            return ImmutableMap.of("status", true);

        } catch (Exception e) {
            log.error("[发货异常]", e);
            return ImmutableMap.of("status", false, "message", "发货失败");
        }
    }

    /**
     * 已提货
     */
    @RequestMapping(value = "/{id}/shipping", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> shipping(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, @PathVariable("id") long id) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }

            orderApplication.shipping(queryChannelService.findOne(QOrder.order.id.eq(id), Order.class));
            logApplication.eventOfMerchant(Securitys.currentUser(), "订单自提", Securitys.getIp(request));

            return ImmutableMap.of("status", true);

        } catch (Exception e) {
            log.error("[提货异常]", e);
            return ImmutableMap.of("status", false, "message", "提货失败");
        }
    }

    /**
     * 去修改订单价格
     */
    @RequestMapping(value = "/{id}/modifyAmount", method = RequestMethod.GET)
    private String modifyAmount(Model model, @PathVariable("id") long id) {

        Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

        model.addAttribute("order", order).addAttribute("_method", "PUT");

        return "supplier/order/modifyAmount";
    }

    @RequestMapping(value = "/{id}/modifyAmount", method = RequestMethod.PUT)
    @ResponseBody
    private Map<String, Object> modifyAmount(HttpServletRequest request, @RequestHeader("X-Requested-With") String requestWith, Order params) {
        try {
            if (!Webs.isAjaxRequest(requestWith)) {
                throw new IllegalRequestException("request must be Ajax!");
            }

            orderApplication.modifyAmount(params);

            logApplication.eventOfMerchant(Securitys.currentUser(), "修改订单价格", Securitys.getIp(request));

            return ImmutableMap.of("status", true);

        } catch (Exception e) {
            log.error("[发货异常]", e);
            return ImmutableMap.of("status", false, "message", "发货失败");
        }
    }


    /**
     * 查看详情
     */
    @RequestMapping(value = "/{id}/detail", method = RequestMethod.GET)
    public String detail(Model model, @PathVariable("id") long id) {

        Order order = queryChannelService.findOne(QOrder.order.id.eq(id), Order.class);

        List<SupplierOrderDelivery> deliveries = queryChannelService.findAll(QSupplierOrderDelivery.supplierOrderDelivery.order.id.eq(id), SupplierOrderDelivery.class);

        model.addAttribute("order", order);
        model.addAttribute("deliveries", deliveries);

        return "supplier/order/detail";
    }

    /**
     * 查看详情
     */
    @RequestMapping(value = "/{orderNo}/orderDetail", method = RequestMethod.GET)
    private String detail(Model model, @PathVariable("orderNo") String orderNo) {

        Order order = queryChannelService.findOne(QOrder.order.orderNo.eq(orderNo), Order.class);


        List<Goods> giftGoodses = Lists.newArrayList();

        //赠品活动订单
        if (order.getMarketingType() == 1) {
            giftGoodses = queryChannelService.findAll("select g.goods from GiftGoods g where g.gift.id = :id ", ImmutableMap.of("id", order.getGiftActivity().getId()), Goods.class);
        }

        model.addAttribute("order", order);
        model.addAttribute("giftgoodses", giftGoodses);

        return "supplier/order/detail";
    }


    /**
     * 条件筛选
     */
    private String builderSQL(String sql, Map<String, Object> params, Order order) throws ParseException {

        if (order.getStatus() > 0) {
            sql += " and u.status = :status ";
            params.put("status", order.getStatus());
        }

        if (null != order.getMerchant() && order.getMerchant().getId() != 0) {
            sql += " and u.merchant.id = :mid ";
            params.put("mid", order.getMerchant().getId());
        }

        if (!Strings.isNullOrEmpty(order.getOrderNo())) {
            sql += " and u.orderNo like :orderno ";
            params.put("orderno", "%" + order.getOrderNo() + "%");
        }

        if (!Strings.isNullOrEmpty(order.getDeliveryMobile())) {
            sql += " and u.deliveryMobile like :deliverymobile ";
            params.put("deliverymobile", "%" + order.getDeliveryMobile() + "%");
        }

        if (!Strings.isNullOrEmpty(order.getDeliveryName())) {
            sql += " and u.deliveryName like :deliveryname ";
            params.put("deliveryname", "%" + order.getDeliveryName() + "%");
        }

        if (!Strings.isNullOrEmpty(order.getBeginTime())) {
            sql += " and u.createTime >= :btime ";
            params.put("btime", new Date(new SimpleDateFormat("yyyy-MM-dd").parse(order.getBeginTime()).getTime()));
        }

        if (!Strings.isNullOrEmpty(order.getEndTime())) {
            sql += " and u.createTime <= :etime ";
            params.put("etime", new Date(new SimpleDateFormat("yyyy-MM-dd").parse(order.getEndTime()).getTime()));
        }

        if (!Strings.isNullOrEmpty(order.getOrderByCreateTime())) {
            sql += " order by u.createTime " + order.getOrderByCreateTime();
        }

        if (!Strings.isNullOrEmpty(order.getOrderByPrice())) {
            sql += " order by u.price " + order.getOrderByPrice();
        }

        if (!sql.contains("order by")) {
            sql += " order by u.createTime desc ";
        }

        return sql;
    }

}
